package net.sf.midollo.net.protocol;

import java.io.IOException;

import net.sf.midollo.io.IOStream;
import net.sf.midollo.utils.Utils;

public class ProtocolRunner implements Runnable {

  protected final IOStream ioRequest;
  protected final ProtocolFactory protocolFactory;
  protected IOException error;

  public ProtocolRunner(IOStream ioRequest, ProtocolFactory protocolFactory) {
    this.ioRequest = ioRequest;
    this.protocolFactory = protocolFactory;
  }

  public IOException getError() {
    return this.error;
  }

  public void runProtocol() throws IOException {
    Protocol protocol = this.protocolFactory.connect(this.ioRequest);
    IOException pendingError = tryRunProtocol(protocol, null);
    pendingError = tryDisconnectProtocol(protocol, pendingError);
    pendingError = tryCloseRequest(pendingError);
    if (pendingError != null)
      throw pendingError;
  }

  public void run() {
    try {
      runProtocol();
      this.error = null;
    } catch (IOException e) {
      this.error = e;
      Utils.log(e.toString());
    }
  }

  protected IOException tryRunProtocol(Protocol protocol, IOException pendingError) {
    protocol.run();
    if (pendingError == null)
      pendingError = protocol.getError();
    return pendingError;
  }

  protected IOException tryDisconnectProtocol(Protocol protocol, IOException pendingError) {
    try {
      protocol.disconnect();
    } catch (IOException e) {
      if (pendingError == null)
        pendingError = e;
    }
    return pendingError;
  }

  protected IOException tryCloseRequest(IOException pendingError) {
    try {
      this.ioRequest.close();
    } catch (IOException e) {
      if (pendingError == null)
        pendingError = e;
    }
    return pendingError;
  }
}
